package com.garbagecode.routetable;

import java.util.ArrayList;
import java.util.List;

import com.garbagecode.routetable.path.Path;
import com.garbagecode.routetable.path.PathImpl;
import com.garbagecode.routetable.path.Segment;

public class Routes {
  private Path head = new PathImpl();

  public Routes() {

  }

  public Routes(Path head) {
    this.head = head;
  }
  
  /**
   * 往路由表里添加路由
   * @param path
   * @param item
   * @return
   */
  public Route add(String path, Object item) {
    if (path == null) {
      throw new IllegalArgumentException("path null");
    }
    
    // 计算路径参数开始的索引
    int index = getFirstPathParameterIndex(path);
    String key = index >= 0
        ? path.substring(0, index)
        : path;
    // 生成路由元信息
    Route route = getRoute(path, item, index);

    head.add(key.toCharArray(), 0, route);
    return route;
  }
  
  /**
   * 返回路径 Path 匹配的路由
   * @param path
   * @return
   */
  public Route get(String path) {
    if (path == null) {
      throw new IllegalArgumentException("path null");
    }
    
    return head.get(path.toCharArray(), 0);
  }
  
  /**
   * 生成路由元信息
   * @param path
   * @param item
   * @param fistPathParameterIndex
   * @return
   */
  protected Route getRoute(String path, Object item, int fistPathParameterIndex) {
    if (path == null) {
      throw new IllegalArgumentException("path null");
    }
    
    // 若没有路径参数
    if (fistPathParameterIndex < 0) {
      return new Route(path, item);
    }
    
    String[] strArray = path.substring(fistPathParameterIndex).split("/", -1);
    List<Segment> segmentList = new ArrayList<Segment>();
    String str = null;
    Segment segment = null;
    
    // 把符号 "/" 分隔的路径添加到集合 segmentList 中
    for (int i = 0; i < strArray.length; i++) {
      str = strArray[i];
      segment = isPathParameter(str)
          ? new Segment(getPathParameterName(str), Segment.TYPE_PARAMETER)
          : new Segment(str, Segment.TYPE_STATIC);
      
      segmentList.add(segment);
    }
    
    return new Route(path, item, fistPathParameterIndex, segmentList);
  }
  
  /**
   * 返回路径参数开始的索引
   * 比如：
   * getFirstPathParameterIndex("/hello/:who"); => 7
   * getFirstPathParameterIndex("/hello/world"); => -1
   * 
   * @param path
   * @return
   */
  protected int getFirstPathParameterIndex(String path) {
    if (path == null) {
      throw new IllegalArgumentException("path null");
    }
    
    return path.indexOf(':');
  }
  
  /**
   * 判断字符串  str 是不是代表路径参数
   * 比如：
   * isPathParameter(":"); // => true
   * isPathParameter(":name"); // => true
   * isPathParameter("name"); // => false
   * 
   * @param str
   * @return
   */
  protected boolean isPathParameter(String str) {
    if (str == null) {
      throw new IllegalArgumentException("str null");
    }
    
    // 这里判断的依据是若字符串以字符 ":" 开头则是路径参数
    return str.startsWith(":");
  }
  
  /**
   * 返回路径参数 str 的名称
   * 比如：
   * getPathParameterName(":name"); // => "name"
   * getPathParameterName(":"); // => ""
   * 
   * @param str
   * @return
   */
  protected String getPathParameterName(String str) {
    if (str == null) {
      throw new IllegalArgumentException("str null");
    }
    
    if (str.isEmpty()) {
      throw new IllegalArgumentException("str required");
    }
    
    if (str.length() == 1) {
      return "";
    }
    
    return str.substring(1);
  }

}
